/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tetris;

import GA.IEvolvingAI;
import java.awt.Color;

/**
 *
 * @author S094182
 */
public class SlightlyLessStupidAI extends StupidAI implements IEvolvingAI {

    private double[] weights;
    private int N_GENES = 7;

    public SlightlyLessStupidAI(int nWeights) {
        this.weights = new double[nWeights];
    }

    @Override
    public void setHeuristic(Object rule) {
        this.weights = (double[]) rule;
        for (int i = 0; i < weights.length; i++) {
            if (Double.isNaN(weights[i]) || Double.isInfinite(weights[i])) {
                this.weights[i] = 1;
            }
        }
    }
    
    public boolean isSquareEmpty(int x, int y, Color[][] board) {
        if (x < 0 || x >= board[0].length || y < 0 || y >= board.length) {
            return x >= 0 && x < board[0].length && y < 0;
        } else {
            return board[y][x] == null;
        }
    }

    public int exposedEdges(Color[][] board) {
        int edges = 0;
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (!isSquareEmpty(j, i, board)) {
                    edges += exposedEdgesFigure(j, i, board);
                }
            }
        }
        return edges;
    }

    public int bumpiness(int[] contour) {
        int bumps = 0;
        for (int i = 0; i < contour.length-1; i++) {
            bumps += Math.abs(contour[i] - contour[i+1]);
        }

        return bumps;
    }

    public int[] contour(Color[][] board) {
        int[] contour = new int[10];
        int width = board[0].length;
        int height = board.length;

        for (int i = 0; i < width; i++) {
            int tmp = 20;
            while(isSquareEmpty(i, height - tmp, board) && tmp > 0)
                tmp--;
            contour[i] = tmp;
        }
        return contour;
    }

    public int chasms(int[] contour) {
        int c = 0;
        for (int i = 0; i < contour.length; i++) {
            if (((i > 0) ? contour[i-1] : 20) >= contour[i] + 3 
                    && contour[i] + 3 <= ((i < 9) ? contour[i+1] : 20))
                    c++;
        }
        return c*10;
    }

    public int getFullLines(Color[][] board) {
        int nrOfLines = 0;
        int width = board[0].length;
        int height = board.length;
        boolean full = true;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                if(isSquareEmpty(j, i, board))
                    full = false;
            }
            if (full) nrOfLines++;;
            full = true;
        }       
        return nrOfLines*10;
    }

    private int exposedEdgesFigure(int x, int y, Color[][] board) {
        int edges = 0;
        if (isSquareEmpty(x - 1, y, board)) {
            edges++;
        }
        if (isSquareEmpty(x + 1, y, board)) {
            edges++;
        }
        if (isSquareEmpty(x, y + 1, board)) {
            edges++;
        }
        if (isSquareEmpty(x, y - 1, board)) {
            edges++;
        }
        return edges;
    }
    
    public int numberOfEdgesTouching(Color[][] board) {
        int touches=0;
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (!isSquareEmpty(j, i, board)) {
                    touches += doesItTouch(j, i, board);
                }
            }
        }
        return touches;
            
    }

    private int doesItTouch(int x, int y, Color[][] board) {
        int touchThis = 0;
        if (x == 0 || x+1 == 10) {
            touchThis++;
        }
        return touchThis;
    }
    
    private int averageHeight(Color[][] board){
        int width = board[0].length;
        int height = board.length;
        int avgHeight = 0;
        
        for (int i = 0; i < width; i++) {
            int pillarHeight = 0;
            for (int j = 0; j < height; j++) {
                if(!isSquareEmpty(i, j, board)) {
                    pillarHeight = j;
                }
            }
            avgHeight += pillarHeight / width;
        }
        
        return avgHeight;
    }
    
    private boolean isLineFull(Color[][] board, int y){
        return false;
    }
    
    private Color[][] removeFullLines(Color[][] board){
        Color[][] newBoard = new Color[board.length][board[0].length];
        
        for (int y = board.length - 1; y >= 0; y--) {
            if (isLineFull(board, y))
                y++;
            else {
                for (int i = 0; i < newBoard[0].length; i++) {
                    newBoard[y][i] = board[y][i];
                }
            }
        }
        return newBoard;
    }

    @Override
    public double rateBoard(Color[][] board) {
        
        int lines = getFullLines(board);
        
        Color[][] nBoard = removeFullLines(board);
        
        int maxHeight = getMaxHeight(nBoard);
        int nrOfHoles = getHoles(nBoard, maxHeight);
        //int nrOfNonFullLines = getNonFullLines(board, maxHeight);
        int exposedEdges = exposedEdges(nBoard);
        int touchingWalls = numberOfEdgesTouching(nBoard);
        //int avgHeight = averageHeight(board);
        int[] tmp = contour(nBoard);
        int bumpy = bumpiness(tmp);
        int chasm = chasms(tmp);

        return nrOfHoles * weights[0] + maxHeight * weights[1] +  exposedEdges * weights[2] + touchingWalls * weights[3]
                + bumpy * weights[4] + lines * weights[5] + chasm * weights[6];
    }
    /*int maxHeight = getMaxHeight(board);
        int nrOfHoles = getHoles(board, maxHeight);
        int exposedEdges = exposedEdges(board);
        int touchingWalls = numberOfEdgesTouching(board);
        int bumpy = bumpiness(board);
        int lines = getFullLines(board);
        int chasm = chasms(board);

        return nrOfHoles * weights[0] + maxHeight * weights[1] +  exposedEdges * weights[3] + touchingWalls * weights[4]
                +  bumpy * weights[6] + lines * weights[5] + chasm * weights[2];

     nrOfNonFullLines * weights[2] + + avgHeight * weights[5] */

    @Override
    public int getNGenes() {
        return N_GENES;
    }


    @Override
    public void feedback(Object obj) {
       
    }
}
